package com.jml.dubbo.server.proxy;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.InetSocketAddress;
import java.net.URLDecoder;
import java.util.List;

import com.jml.dubbo.server.discover.ServiceDiscover;
import com.jml.dubbo.server.discover.ServiceDiscoverImpl;
import com.jml.dubbo.server.handler.DubboClientHandler;
import com.jml.dubbo.server.loadBalance.LoadBalance;
import com.jml.dubbo.server.loadBalance.impl.LoopLoadBalance;
import com.jml.dubbo.server.marshalling.MarshallingCodeCFactory;
import com.jml.dubbo.server.req.RpcRequest;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;


public class RpcClientProxy {

    public <T> T create(final Class<T> interfaceClass) {
        return (T) Proxy.newProxyInstance(interfaceClass.getClassLoader(), new Class[]{interfaceClass}, new InvocationHandler() {

            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                // 使用我们的代理拼接我们的地址
                ServiceDiscover serviceDiscover = new ServiceDiscoverImpl();
                String serviceName = interfaceClass.getName();
                List<String> discover = serviceDiscover.getDiscover(serviceName);
                // 采用我们默认的轮训负载均衡器
                LoadBalance loadBalance = new LoopLoadBalance();
                // 获取到地址 mayikt://192.168.110:8080
                String select = URLDecoder.decode(loadBalance.select(discover));
                String[] split = select.split(":");
                String host = split[1].replace("//", "");
                String port = split[2];
                // 封装具体调用的参数
                RpcRequest rpcRequest = new RpcRequest(serviceName, method.getName(), method.getParameterTypes(), args);
                // 启动我们的netty客户端发送消息
                return sendMsg(host, Integer.parseInt(port), rpcRequest);
            }
        });
    }

    public Object sendMsg(String host, int port, RpcRequest rpcRequest) {
        final DubboClientHandler dubboClientHandler = new DubboClientHandler();
        //创建nioEventLoopGroup
        NioEventLoopGroup group = new NioEventLoopGroup();
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group).channel(NioSocketChannel.class)
                .remoteAddress(new InetSocketAddress(host, port))
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingDecoder());
                        ch.pipeline().addLast(MarshallingCodeCFactory.buildMarshallingEncoder());
                        ch.pipeline().addLast(dubboClientHandler);
                    }
                });
        try {
            // 发起同步连接
            ChannelFuture sync = bootstrap.connect().sync();
            // 客户端发送我们的对象
            System.out.println("生产者发送消息:" + rpcRequest.toString());
            sync.channel().writeAndFlush(rpcRequest);
            sync.channel().closeFuture().sync();
        } catch (Exception e) {
            e.printStackTrace();

        } finally {
            group.shutdownGracefully();
        }
        return dubboClientHandler.getResponse();

    }
}
